package com.autumn.oauth2.zero.configuration;

import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;

import com.autumn.oauth2.zero.EnableAutumnAuthorizationServer;
import com.autumn.spring.boot.bean.AbstractImportBeanDefinitionRegister;
import com.autumn.spring.boot.bean.BeanDefinitionRegisterManager;
import com.autumn.util.ExceptionUtils;
import com.autumn.util.StringUtils;
import com.autumn.util.TypeUtils;
import com.autumn.util.function.FunctionOneAction;

/**
 * 授权服务器定义注册
 * 
 * @author 老码农
 *
 *         2018-04-12 19:10:40
 */
public class AuthorizationServerDefinitionRegister extends AbstractImportBeanDefinitionRegister
		implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {

	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(
				importingClassMetadata.getAnnotationAttributes(EnableAutumnAuthorizationServer.class.getName()));

		BeanDefinitionRegisterManager regManager = new BeanDefinitionRegisterManager(this.getEnvironment(),
				this.getResourceLoader(), registry);

		String beanName;
		
		this.registerBean(regManager, annoAttrs, "userServiceType", BeanConsts.AUTUMN_USER_DETAILS_SERVICE, null);
		beanName = this.registerBean(regManager, annoAttrs, "passwordEncoderType", null,
				null);
		this.registerBean(regManager, annoAttrs, "passwordProviderType", BeanConsts.AUTUMN_PASSWORD_PROVIDER, (def) -> {
			def.getPropertyValues().addPropertyValue("passwordEncoder",
					new RuntimeBeanReference(beanName));

		});
		this.registerBean(regManager, annoAttrs, "securityConfigurerAdapterType", null, null);
		this.registerBean(regManager, annoAttrs, "serverConfigurerAdapterType", null, null);

	}

	private String registerBean(BeanDefinitionRegisterManager regManager, AnnotationAttributes attributes,
			String attributesName, String beanName, FunctionOneAction<GenericBeanDefinition> action) {
		Class<?> beantype = attributes.getClass(attributesName);
		if (TypeUtils.isAbstract(beantype)) {
			ExceptionUtils.throwConfigureException(beantype.getName() + " 必须是实现类型。");
		}
		if (StringUtils.isNullOrBlank(beanName)) {
			beanName = regManager.generateBeanName(beantype);
		}
		GenericBeanDefinition beanDefinition = regManager.createBeanDefinition(beantype, null, null, null);
		beanDefinition.setPrimary(true);
		if (action != null) {
			action.apply(beanDefinition);
		}
		regManager.registerBean(beanName, beanDefinition);
		return beanName;
	}

}
